package com.recharge.service.impl;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.recharge.common.excetion.CustomException;
import com.recharge.common.result.ResultDO;
import com.recharge.common.util.Constant;
import com.recharge.core.entity.RoleEntity;
import com.recharge.core.entity.RolePermissionEntity;
import com.recharge.core.mapper.RoleMapper;
import com.recharge.core.mapper.RolePermissionMapper;
import com.recharge.domain.query.PermissionQueryDO;
import com.recharge.domain.vo.PermissionDO;
import com.recharge.domain.vo.RoleDO;
import com.recharge.domain.vo.UserLoginDO;
import com.recharge.service.PermissionService;
import com.recharge.service.RoleService;
import com.recharge.service.ShiroService;
import com.recharge.service.UserService;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.util.CollectionUtils;
import org.apache.shiro.web.filter.mgt.DefaultFilterChainManager;
import org.apache.shiro.web.filter.mgt.PathMatchingFilterChainResolver;
import org.apache.shiro.web.servlet.AbstractShiroFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.sql.Wrapper;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.StringJoiner;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.stream.Collectors;

@Service
public class ShiroServiceImpl implements ShiroService {

    private Logger logger = LoggerFactory.getLogger(this.getClass().getName());

    @Autowired
    private UserService userService;

    @Autowired
    private RoleMapper roleMapper;

    @Autowired
    private PermissionService permissionService;

    @Autowired
    private RolePermissionMapper rolePermissionMapper;

    @Value("${application.contextPath}")
    private String contextPath;

    @Override
    public Map<String, String> loadFilterChainDefinitionMap() {
        // 权限控制map
        Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
        // 配置过滤:不会被拦截的链接 -> 放行 start ----------------------------------------------------------
        //放行上下文
        filterChainDefinitionMap.put(contextPath, "anon");
        // 放行Swagger2页面，需要放行这些
        filterChainDefinitionMap.put("/webjars/**", "anon");
        filterChainDefinitionMap.put("/swagger-ui.html","anon");
        filterChainDefinitionMap.put("/swagger/**","anon");
        filterChainDefinitionMap.put("/webjars/**", "anon");
        filterChainDefinitionMap.put("/swagger-resources/**","anon");
        filterChainDefinitionMap.put("/v2/**","anon");
        filterChainDefinitionMap.put("/static/**", "anon");

        // 登陆
        filterChainDefinitionMap.put("/index/login.html", "anon");
        //对外开发接口
        filterChainDefinitionMap.put("/api/**", "anon");
        // 放行 end ----------------------------------------------------------

        // 从数据库或缓存中查取出来的url与resources对应则不会被拦截 放行
        PermissionQueryDO query = new PermissionQueryDO();
        query.setQueryType(Constant.BUTT);
        ResultDO result  = permissionService.getAll(query);
        if(result.isSuccess()){
            List<PermissionDO> permissionList = (List<PermissionDO>) result.getModel(ResultDO.FIRST_MODEL_KEY);
            if ( !CollectionUtils.isEmpty( permissionList ) ) {
                List<RoleEntity> resultRole = roleMapper.selectList(Wrappers.<RoleEntity>lambdaQuery().eq(RoleEntity::getIsDelete, Constant.IS_DELETE_FALSE));
                List<RolePermissionEntity> rolePermissionList = rolePermissionMapper.selectList(null);
                permissionList.stream().forEach( e -> {
                    if ( StringUtils.isNotBlank( e.getRequestUrl() ) ) {
                        StringJoiner zqRoles = new StringJoiner(",", "zqRoles[", "]");
                        if(!CollectionUtils.isEmpty( rolePermissionList ) ){
                            rolePermissionList.stream().forEach( item -> {
                                if(item.getPermissionId().equals(e.getId())){
                                    if(!CollectionUtils.isEmpty( resultRole ) ){
                                        List<String> roleCodeList = resultRole.stream().map(RoleEntity::getCode).distinct().collect(Collectors.toList());
                                        roleCodeList.stream().forEach( roleCode -> zqRoles.add(roleCode));
                                    }
                                }
                            });
                        }
//                        // 根据url查询相关联的角色名,拼接自定义的角色权限
//                        ResultDO resultRole = roleService.selectRoleByPermissionId( e.getId() );
//                        StringJoiner zqRoles = new StringJoiner(",", "zqRoles[", "]");
//                        if(resultRole.isSuccess()){
//                            List<RoleDO> roleList = (List<RoleDO>) resultRole.getModel(ResultDO.FIRST_MODEL_KEY);
//                            if ( !CollectionUtils.isEmpty( roleList ) ){
//                                roleList.stream().forEach( f -> {
//                                    zqRoles.add( f.getCode() );
//                                });
//                            }
//                        }

                        // 注意过滤器配置顺序不能颠倒
                        // ① 认证登录
                        // ② 认证自定义的token过滤器 - 判断token是否有效
                        // ③ 角色权限 zqRoles：自定义的只需要满足其中一个角色即可访问  ;  roles[admin,guest] : 默认需要每个参数满足才算通过，相当于hasAllRoles()方法
                        // ④ zqPerms:认证自定义的url过滤器拦截权限  【注：多个过滤器用 , 分割】
    //                    filterChainDefinitionMap.put( "/api" + e.getUrl(),"authc,token,roles[admin,guest],zqPerms[" + e.getResources() + "]" );
                        filterChainDefinitionMap.put(contextPath + e.getRequestUrl(),"token,"+ zqRoles.toString() +",permission[" + e.getCode() + "]" );
    //                        filterChainDefinitionMap.put("/api/system/user/listPage", "authc,token,zqPerms[user1]"); // 写死的一种用法
                    }
                });
            }
        }
        // ⑤ 认证登录  【注：map不能存放相同key】
        filterChainDefinitionMap.put("/**", "token");
        return filterChainDefinitionMap;
    }

//    @Override
//    public void updatePermission(ShiroFilterFactoryBean shiroFilterFactoryBean, Integer roleId, Boolean isRemoveSession) {
//        synchronized (this) {
//            AbstractShiroFilter shiroFilter;
//            try {
//                shiroFilter = (AbstractShiroFilter) shiroFilterFactoryBean.getObject();
//            } catch (Exception e) {
//                throw new CustomException("get ShiroFilter from shiroFilterFactoryBean error!");
//            }
//            PathMatchingFilterChainResolver filterChainResolver = (PathMatchingFilterChainResolver) shiroFilter.getFilterChainResolver();
//            DefaultFilterChainManager manager = (DefaultFilterChainManager) filterChainResolver.getFilterChainManager();
//
//            // 清空拦截管理器中的存储
//            manager.getFilterChains().clear();
//            // 清空拦截工厂中的存储,如果不清空这里,还会把之前的带进去
//            //            ps:如果仅仅是更新的话,可以根据这里的 map 遍历数据修改,重新整理好权限再一起添加
//            shiroFilterFactoryBean.getFilterChainDefinitionMap().clear();
//            // 动态查询数据库中所有权限
//            shiroFilterFactoryBean.setFilterChainDefinitionMap(loadFilterChainDefinitionMap());
//            // 重新构建生成拦截
//            Map<String, String> chains = shiroFilterFactoryBean.getFilterChainDefinitionMap();
//            for (Map.Entry<String, String> entry : chains.entrySet()) {
//                manager.createChain(entry.getKey(), entry.getValue());
//            }
//            logger.debug("--------------- 动态生成url权限成功！ ---------------");
//
//            // 动态更新该角色相关联的用户shiro权限
//            if(roleId != null){
//                updatePermissionByRoleId(roleId,isRemoveSession);
//            }
//        }
//    }
//
//    @Override
//    public void updatePermissionByRoleId(Integer roleId, Boolean isRemoveSession) {
//        // 查询当前角色的用户shiro缓存信息 -> 实现动态权限
//        ResultDO resultUser = userService.selectUserByRoleId(roleId);
//        List<UserLoginDO> userList = null;
//        if(resultUser.isSuccess()){
//           userList = (List<UserLoginDO>) resultUser.getModel(ResultDO.FIRST_MODEL_KEY);
//        }
//        // 删除当前角色关联的用户缓存信息,用户再次访问接口时会重新授权 ; isRemoveSession为true时删除Session -> 即强制用户退出
////        if ( !CollectionUtils.isEmpty( userList ) ) {
////            for (UserLoginDO user : userList) {
////                ShiroUtils.deleteCache(user.getUsername(), isRemoveSession);
////            }
////        }
//        logger.debug("--------------- 动态修改用户权限成功！ ---------------");
//    }

}